/*
 * es325.h  --  ES325 Soc Audio driver
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#ifndef _ES325_H
#define _ES325_H

#include <sound/soc.h>

#define ES325_READ_VE_OFFSET		0x0804
#define ES325_READ_VE_WIDTH		4
#define ES325_WRITE_VE_OFFSET		0x0800
#define ES325_WRITE_VE_WIDTH		4

#define ES325_MCLK_DIV			0x0000
#define ES325_CLASSD_CLK_DIV		0x0001
#define ES325_CP_CLK_DIV		0x0002

#define ES325_BOOT_CMD			0x0001
#define ES325_BOOT_ACK			0x01010101

#define ES325_SYNC_CMD			0x8000
#define ES325_SYNC_POLLING		0x0000
#define ES325_SYNC_INTR_ACITVE_LOW	0x0001
#define ES325_SYNC_INTR_ACITVE_HIGH	0x0002
#define ES325_SYNC_INTR_FALLING_EDGE	0x0003
#define ES325_SYNC_INTR_RISING_EDGE	0x0004
#define ES325_SYNC_ACK			0x80000000

#define ES325_RESET_CMD			0x8002
#define ES325_RESET_IMMED		0x0000
#define ES325_RESET_DELAYED		0x0001

#define ES325_SET_POWER_STATE		0x8010
#define ES325_POWER_STATE_SLEEP		0x0001
#define ES325_POWER_STATE_NORMAL	0x0004
#define ES325_POWER_STATE_VS_OVERLAY	0x0005
#define ES325_POWER_STATE_VS_LOWPWR	0x0006
#define ES325_POWER_STATE_SLEEP_PENDING	0x0007
#define ES325_POWER_STATE_SLEEP_REQUESTED	0x0008

#define ES325_SMOOTH_MUTE		0x904E0000
/*
 * bit15 - reserved
 * bit[14:12] - access type
 * bit11 - commit = 0, staged = 1
 * bit[10:0] - psuedo address
 */
#define ES325_ACCESS_MASK	(7 << 12)
#define ES325_ALGO_ACCESS	(0 << 12)
#define ES325_DEV_ACCESS	(1 << 12)
#define ES325_CMD_ACCESS	(2 << 12)
#define ES325_OTHER_ACCESS	(3 << 12)

#define ES325_CMD_MASK		(1 << 11)
#define ES325_STAGED_CMD	(1 << 11)
#define ES325_COMMIT_CMD	(0 << 11)

#define ES325_ADDR_MASK		0x7ff

#define ES325_STAGED_MSG_BIT	(1 << 13)
/*
 * Device parameter command codes
 */
#define ES325_DEV_PARAM_OFFSET		0x2000
#define ES325_GET_DEV_PARAM		0x800b
#define ES325_SET_DEV_PARAM_ID		0x900c
#define ES325_SET_DEV_PARAM		0x900d

/*
 * Algoithm parameter command codes
 */
#define ES325_ALGO_PARAM_OFFSET		0x0000
#define ES325_GET_ALGO_PARAM		0x8016
#define ES325_SET_ALGO_PARAM_ID		0x9017
#define ES325_SET_ALGO_PARAM		0x9018

/* Speculative sleep delay in msecs */
#define ES325_SLEEP_DELAY	300

/*
 * addresses
 */
enum {
	ES325_MIC_CONFIG,
	ES325_AEC_MODE,
	ES325_TX_AGC,
	ES325_TX_AGC_TARGET_LEVEL,
	ES325_TX_AGC_NOISE_FLOOR,
	ES325_TX_AGC_SNR_IMPROVEMENT,
	ES325_VEQ_ENABLE,
	ES325_RX_OUT_LIMITER_MAX_LEVEL,
	ES325_RX_NOISE_SUPPRESS,
	ES325_RX_STS,
	ES325_RX_STS_RATE,
	ES325_AEC_SPEAKER_VOLUME,
	ES325_SIDETONE,
	ES325_SIDETONE_GAIN,
	ES325_TX_COMFORT_NOISE,
	ES325_TX_COMFORT_NOISE_LEVEL,
	ES325_ALGORITHM_RESET,
	ES325_RX_POST_EQ,
	ES325_TX_POST_EQ,
	ES325_AEC_CNG,
	ES325_VEQ_NOISE_ESTIMATION_ADJUSTMENT,
	ES325_TX_AGC_SLEW_RATE_UP,
	ES325_TX_AGC_SLEW_RATE_DOWN,
	ES325_RX_AGC,
	ES325_RX_AGC_TARGET_LEVEL,
	ES325_RX_AGC_NOISE_FLOOR,
	ES325_RX_AGC_SNR_IMPROVEMENT,
	ES325_RX_AGC_SLEW_RATE_UP,
	ES325_RX_AGC_SLEW_RATE_DOWN,
	ES325_AEC_CNG_GAIN,
	ES325_TX_MBC,
	ES325_RX_MBC,
	ES325_AEC_ESE,
	ES325_TX_NS_ADAPTATION_SPEED,
	ES325_TX_SNR_ESTIMATE,
	ES325_VEQ_MAX_GAIN,
	ES325_TX_AGC_GUARDBAND,
	ES325_RX_AGC_GUARDBAND,
	ES325_TX_OUT_LIMITER_MAX_LEVEL,
	ES325_TX_IN_LIMITER_MAX_LEVEL,
	ES325_RX_NS_ADAPTATION_SPEED,
	ES325_AEC_VARIABLE_ECHO_REF_DELAY,
	ES325_TX_NOISE_SUPPRESS_LEVEL,
	ES325_RX_NOISE_SUPPRESS_LEVEL,
	ES325_RX_CNG,
	ES325_RX_CNG_GAIN,
	ES325_TX_AGC_MAX_GAIN,
	ES325_RX_AGC_MAX_GAIN,
	ES325_AVALON_API_VERSION_LO,
	ES325_AVALON_API_VERSION_HI,
	ES325_AVALON_AV_PROCESSOR,
	ES325_AVALON_AV_CONFIG,
	ES325_AVALON_EQ_PRESET,
	ES325_AVALON_STEREO_WIDTH,
	ES325_AVALON_AV_DIGITAL_OUT_GAIN,
	ES325_AVALON_TDMBC,
	ES325_AVALON_AV_OUT_LIMIT,
	ES325_AVALON_STEREO_WIDENING,
	ES325_AVALON_STAT_NS,
	ES325_AVALON_STAT_NS_SUPPRESS,
	ES325_AVALON_STAT_NS_ADAP_SPEED,
	ES325_AVALON_STAT_NS_MODE,
	ES325_AVLALON_STAT_NS_MAX_NOISE_ENERGY,
	ES325_AVALON_VBB,
	ES325_AVALON_VBB_STRENGTH,
	ES325_AVALON_EQ_MODE,
	ES325_AVALON_EQ_GRAPHIC_BAND1_GAIN,
	ES325_AVALON_EQ_GRAPHIC_BAND2_GAIN,
	ES325_AVALON_EQ_GRAPHIC_BAND3_GAIN,
	ES325_AVALON_EQ_GRAPHIC_BAND4_GAIN,
	ES325_AVALON_EQ_GRAPHIC_BAND5_GAIN,
	ES325_AVALON_EQ_GRAPHIC_BAND6_GAIN,
	ES325_AVALON_EQ_GRAPHIC_BAND7_GAIN,
	ES325_AVALON_EQ_GRAPHIC_BAND8_GAIN,
	ES325_AVALON_EQ_GRAPHIC_BAND9_GAIN,
	ES325_AVALON_EQ_GRAPHIC_BAND10_GAIN,
	ES325_AVALON_TDDRC,
	ES325_AVALON_TDDRC_STRENGTH,
	ES325_AVALON_LIMITER,
	ES325_AVALON_EQ,
	ES325_DIRAC,
	ES325_DIRAC_OUT_HEADROOM_LIMITER,
	ES325_DIRAC_MODE,
	ES325_DIRAC_IN_HEADROOM_LIMITER,
	ES325_DIRAC_COMFORT_NOISE,
	ES325_DIRAC_COMFORT_NOISE_LEVEL,
	ES325_DIRAC_NARRATOR_VQOS,
	ES325_DIRAC_NARRATOR_POSITION_SUPPRESS,
	ES325_DIRAC_NARRATOR_AGC_OUT,
	ES325_DIRAC_NARRATOR_AGC_SPEECH_TARGET,
	ES325_DIRAC_NARRATOR_AGC_SNR_IMPROVE,
	ES325_DIRAC_NARRATOR_AGC_NOISE_FLOOR,
	ES325_DIRAC_NARRATOR_AGC_MAX_GAIN,
	ES325_DIRAC_NARRATOR_AGC_UP_RATE,
	ES325_DIRAC_NARRATOR_AGC_DOWN_RATE,
	ES325_DIRAC_NARRATOR_AGC_GUARDBAND,
	ES325_DIRAC_NARRATOR_POST_EQ_MODE,
	ES325_DIRAC_NARRATOR_MBC_MODE,
	ES325_DIRAC_SCENE_BEAM_WIDTH,
	ES325_DIRAC_SCENE_AGC_OUT,
	ES325_DIRAC_SCENE_AGC_SPEECH_TARGET,
	ES325_DIRAC_SCENE_AGC_SNR_IMPROVE,
	ES325_DIRAC_SCENE_AGC_NOISE_FLOOR,
	ES325_DIRAC_SCENE_AGC_MAX_GAIN,
	ES325_DIRAC_SCENE_AGC_UP_RATE,
	ES325_DIRAC_SCENE_AGC_DOWN_RATE,
	ES325_DIRAC_SCENE_AGC_GUARDBAND,
	ES325_DIRAC_SCENE_VQOS,
	ES325_DIRAC_SCENE_POST_EQ_MODE,
	ES325_DIRAC_SCENE_MBC_MODE,
	ES325_TONE_PARAM_API_VERSION_LO,
	ES325_TONE_PARAM_API_VERSION_HI,
	ES325_TONE_PARAM_ENABLE_BEEP_SYS,
	ES325_TONE_PARAM_ENABLE_GEN_BEEP,
	ES325_TONE_PARAM_GEN_BEEP_ON,
	ES325_TONE_PARAM_GEN_BEEP_FREQ1,
	ES325_TONE_PARAM_GEN_BEEP_FREQ2,
	ES325_TONE_PARAM_GEN_BEEP_PAN_LR,
	ES325_TONE_PARAM_GEN_BEEP_GAIN,
	ES325_DEREVERB_ENABLE,
	ES325_DEREVERB_GAIN,
	ES325_BWE_ENABLE,
	ES325_BWE_HIGH_BAND_GAIN,
	ES325_BWE_MAX_SNR,
	ES325_BWE_POST_EQ_ENABLE,
	ES325_PORTA_WORD_LEN,
	ES325_PORTA_TDM_SLOTS_PER_FRAME,
	ES325_PORTA_TX_DELAY_FROM_FS,
	ES325_PORTA_RX_DELAY_FROM_FS,
	ES325_PORTA_LATCH_EDGE,
	ES325_PORTA_ENDIAN,
	ES325_PORTA_TRISTATE,
	ES325_PORTA_AUDIO_PORT_MODE,
	ES325_PORTA_TDM_ENABLED,
	ES325_PORTA_CLOCK_CONTROL,
	ES325_PORTA_DATA_JUSTIFICATION,
	ES325_PORTA_FS_DURATION,
	ES325_PORTB_WORD_LEN,
	ES325_PORTB_TDM_SLOTS_PER_FRAME,
	ES325_PORTB_TX_DELAY_FROM_FS,
	ES325_PORTB_RX_DELAY_FROM_FS,
	ES325_PORTB_LATCH_EDGE,
	ES325_PORTB_ENDIAN,
	ES325_PORTB_TRISTATE,
	ES325_PORTB_AUDIO_PORT_MODE,
	ES325_PORTB_TDM_ENABLED,
	ES325_PORTB_CLOCK_CONTROL,
	ES325_PORTB_DATA_JUSTIFICATION,
	ES325_PORTB_FS_DURATION,
	ES325_PORTC_WORD_LEN,
	ES325_PORTC_TDM_SLOTS_PER_FRAME,
	ES325_PORTC_TX_DELAY_FROM_FS,
	ES325_PORTC_RX_DELAY_FROM_FS,
	ES325_PORTC_LATCH_EDGE,
	ES325_PORTC_ENDIAN,
	ES325_PORTC_TRISTATE,
	ES325_PORTC_AUDIO_PORT_MODE,
	ES325_PORTC_TDM_ENABLED,
	ES325_PORTC_CLOCK_CONTROL,
	ES325_PORTC_DATA_JUSTIFICATION,
	ES325_PORTC_FS_DURATION,
	ES325_PORTD_WORD_LEN,
	ES325_PORTD_TDM_SLOTS_PER_FRAME,
	ES325_PORTD_TX_DELAY_FROM_FS,
	ES325_PORTD_RX_DELAY_FROM_FS,
	ES325_PORTD_LATCH_EDGE,
	ES325_PORTD_ENDIAN,
	ES325_PORTD_TRISTATE,
	ES325_PORTD_AUDIO_PORT_MODE,
	ES325_PORTD_TDM_ENABLED,
	ES325_PORTD_CLOCK_CONTROL,
	ES325_PORTD_DATA_JUSTIFICATION,
	ES325_PORTD_FS_DURATION,
	ES325_SLIMBUS_LINK_MULTI_CHANNEL,
	ES325_POWER_STATE,
	ES325_STREAMING,
	ES325_FE_STREAMING,
	ES325_PRESET,
	ES325_ALGO_STATS,
	ES325_ALGO_PROCESSING,
	ES325_ALGO_SAMPLE_RATE,
	ES325_SMOOTH_RATE,
	ES325_CHANGE_STATUS,
	ES325_DIGITAL_PASS_THROUGH,
	ES325_DATA_PATH,
	ES325_ALGORITHM,
	ES325_MIX_SAMPLE_RATE,
	ES325_SIGNAL_RMS_PORTA_DIN_LEFT,
	ES325_SIGNAL_RMS_PORTA_DIN_RIGHT,
	ES325_SIGNAL_RMS_PORTA_DOUT_LEFT,
	ES325_SIGNAL_RMS_PORTA_DOUT_RIGHT,
	ES325_SIGNAL_RMS_PORTB_DIN_LEFT,
	ES325_SIGNAL_RMS_PORTB_DIN_RIGHT,
	ES325_SIGNAL_RMS_PORTB_DOUT_LEFT,
	ES325_SIGNAL_RMS_PORTB_DOUT_RIGHT,
	ES325_SIGNAL_RMS_PORTC_DIN_LEFT,
	ES325_SIGNAL_RMS_PORTC_DIN_RIGHT,
	ES325_SIGNAL_RMS_PORTC_DOUT_LEFT,
	ES325_SIGNAL_RMS_PORTC_DOUT_RIGHT,
	ES325_SIGNAL_RMS_PORTD_DIN_LEFT,
	ES325_SIGNAL_RMS_PORTD_DIN_RIGHT,
	ES325_SIGNAL_RMS_PORTD_DOUT_LEFT,
	ES325_SIGNAL_RMS_PORTD_DOUT_RIGHT,
	ES325_SIGNAL_PEAK_PORTA_DIN_LEFT,
	ES325_SIGNAL_PEAK_PORTA_DIN_RIGHT,
	ES325_SIGNAL_PEAK_PORTA_DOUT_LEFT,
	ES325_SIGNAL_PEAK_PORTA_DOUT_RIGHT,
	ES325_SIGNAL_PEAK_PORTB_DIN_LEFT,
	ES325_SIGNAL_PEAK_PORTB_DIN_RIGHT,
	ES325_SIGNAL_PEAK_PORTB_DOUT_LEFT,
	ES325_SIGNAL_PEAK_PORTB_DOUT_RIGHT,
	ES325_SIGNAL_PEAK_PORTC_DIN_LEFT,
	ES325_SIGNAL_PEAK_PORTC_DIN_RIGHT,
	ES325_SIGNAL_PEAK_PORTC_DOUT_LEFT,
	ES325_SIGNAL_PEAK_PORTC_DOUT_RIGHT,
	ES325_SIGNAL_PEAK_PORTD_DIN_LEFT,
	ES325_SIGNAL_PEAK_PORTD_DIN_RIGHT,
	ES325_SIGNAL_PEAK_PORTD_DOUT_LEFT,
	ES325_SIGNAL_PEAK_PORTD_DOUT_RIGHT,
	ES325_DIGITAL_GAIN_PRIMARY,
	ES325_DIGITAL_GAIN_SECONDARY,
	ES325_DIGITAL_GAIN_TERTIARY,
	ES325_DIGITAL_GAIN_QUAD,
	ES325_DIGITAL_GAIN_FEIN,
	ES325_DIGITAL_GAIN_AUDIN1,
	ES325_DIGITAL_GAIN_AUDIN2,
	ES325_DIGITAL_GAIN_AUDIN3,
	ES325_DIGITAL_GAIN_AUDIN4,
	ES325_DIGITAL_GAIN_UITONE1,
	ES325_DIGITAL_GAIN_UITONE2,
	ES325_DIGITAL_GAIN_CSOUT,
	ES325_DIGITAL_GAIN_FEOUT1,
	ES325_DIGITAL_GAIN_FEOUT2,
	ES325_DIGITAL_GAIN_AUDOUT1,
	ES325_DIGITAL_GAIN_AUDOUT2,
	ES325_DIGITAL_GAIN_AUDOUT3,
	ES325_DIGITAL_GAIN_AUDOUT4,
	ES325_PORTA_TIMING,
	ES325_PORTB_TIMING,
	ES325_PORTC_TIMING,
	ES325_PORTD_TIMING,
	ES325_FLUSH,
	ES325_FW_FIRST_CHAR,
	ES325_FW_NEXT_CHAR,
	ES325_API_ADDR_MAX,
};

#define ES325_SLIM_CH_RX_OFFSET		152
#define ES325_SLIM_CH_TX_OFFSET		156
/* #define ES325_SLIM_RX_PORTS		10 */
#define ES325_SLIM_RX_PORTS		6
#define ES325_SLIM_TX_PORTS		6

#define ES325_NUM_CODEC_SLIM_DAIS	6

#define ES325_SLIM_1_PB		1
#define ES325_SLIM_1_CAP	2
#define ES325_SLIM_2_PB		3
#define ES325_SLIM_2_CAP	4
#define ES325_SLIM_3_PB		5
#define ES325_SLIM_3_CAP	6

#define ES325_NUM_CODEC_I2S_DAIS	4

#define ES325_I2S_PORTA		7
#define ES325_I2S_PORTB		8
#define ES325_I2S_PORTC		9
#define ES325_I2S_PORTD		10

#define ES325_NUM_CODEC_DAIS	(ES325_NUM_CODEC_SLIM_DAIS + ES325_NUM_CODEC_I2S_DAIS)

#define ES325_SLIM_INTF		0
#define ES325_I2C_INTF		1

struct es325_slim_dai_data {
	unsigned int rate;
	unsigned int *ch_num;
	unsigned int ch_act;
	unsigned int ch_tot;
};

struct es325_slim_ch {
	u32	sph;
	u32	ch_num;
	u16	ch_h;
	u16	grph;
};

struct es325_priv {
	struct device *dev;
	struct snd_soc_codec *codec;
	struct firmware *fw;

	unsigned int intf;

	struct esxxx_platform_data *pdata;

	int (*dev_read)(struct es325_priv *es325, u8 *buf, int len);
	int (*dev_write)(struct es325_priv *es325, const u8 *buf, int len);

	struct i2c_client *i2c_client;
	struct slim_device *intf_client;
	struct slim_device *gen0_client;

	struct mutex api_mutex;
	struct es325_slim_dai_data dai[ES325_NUM_CODEC_SLIM_DAIS];
	struct es325_slim_ch slim_rx[ES325_SLIM_RX_PORTS];
	struct es325_slim_ch slim_tx[ES325_SLIM_TX_PORTS];
	struct mutex pm_mutex;
	int clock_enabled;
	int firmware_downloaded;
	int pm_state;
	struct delayed_work sleep_work;

	long internal_route_num;
	unsigned int rx1_route_enable;
	unsigned int tx1_route_enable;
	unsigned int rx2_route_enable;

	unsigned int ap_tx1_ch_cnt;
};

extern struct es325_priv es325_priv;
extern struct snd_soc_codec_driver soc_codec_dev_es325;
extern struct snd_soc_dai_driver es325_dai[];

extern int es325_core_probe(struct device *dev);

extern int es325_bootup(struct es325_priv *es325);

extern int fw_download(void *arg);

#endif /* _ES325_H */
